package com.upb.webserver.host;

import com.upb.webserver.common.constant.Constant;
import com.upb.webserver.common.enums.PlatformEnum;
import com.upb.webserver.common.exception.WebServerException;
import com.upb.webserver.common.pojo.base.BasePageResponse;
import com.upb.webserver.common.pojo.host.RspHostVO;
import com.upb.webserver.common.properties.WebServerProperties;
import com.upb.webserver.common.returncode.ConstantCode;
import com.upb.webserver.common.tools.JsonUtils;
import com.upb.webserver.common.tools.MybatisExampleTools;
import com.upb.webserver.dao.entity.TbHost;
import com.upb.webserver.dao.entity.TbHostExample;
import com.upb.webserver.dao.mapper.TbCompanyMapper;
import com.upb.webserver.dao.mapper.TbHostMapper;
import com.upb.webserver.dao.mapper.TbOrgMapper;
import com.upb.webserver.shell.ShellService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * services for account data.
 */
@Slf4j
@Service
public class HostManager {
    @Autowired
    private TbHostMapper hostMapper;
    @Autowired
    private TbOrgMapper orgMapper;
    @Autowired
    private TbCompanyMapper companyMapper;

    @Autowired
    private WebServerProperties properties;
    @Autowired
    private ShellService shellService;

    /**
     * query count by HostId.
     *
     * @param orgId
     * @return
     */
    public long countByOrgId(int orgId) {
        TbHostExample example = new TbHostExample();
        TbHostExample.Criteria criteria = example.createCriteria();
        criteria.andOrgIdEqualTo(orgId);
        return hostMapper.countByExample(example);
    }


//    /**
//     * @param hostIdList
//     * @return
//     */
//    public String checkHostListEnvironment(List<Integer> hostIdList) {
//        log.info("start exec method [checkHostListEnvironment].  hostIdList:{}", JsonUtils.objToString(hostIdList));
//        if (CollectionUtil.isEmpty(hostIdList)) return "";
//
//        StringBuffer stringBuffer = new StringBuffer();
//        for (int i = 0; i < hostIdList.size(); i++) {
//            Pair<Integer, String> checkRspPair = checkHostEnvironment(hostIdList.get(i));
//            stringBuffer.append("[")
//                    .append(JsonUtils.objToString(checkRspPair))
//                    .append("]");
//            if (i < hostIdList.size() - 1) stringBuffer.append(",");
//        }
//
//        log.info("success exec method [checkHostListEnvironment].  result:{}", stringBuffer.toString());
//        return stringBuffer.toString();
//    }

    /**
     * @param hostId
     */
//    public Pair<Integer, String> checkHostEnvironment(int hostId) {
//        log.info("start exec method [checkHostEnvironment].  hostId:{}", hostId);
//
//        //dos2unix
//        dos2unix();
//
//        //check host id
//        TbHost tbHost = hostMapper.selectByPrimaryKey(hostId);
//        if (Objects.isNull(tbHost)) {
//            log.warn("fail exec method [checkHostEnvironment], invalid hostId:{}", hostId);
//            return Pair.of(hostId, "invalid hostId");
//        }
//
////        //TODO 方案待讨论
////        tbHost.setStatus(HostStatusEnum.NORMAL.getId());
////        tbHost.setGmtModified(new Date());
////        hostMapper.updateByPrimaryKey(tbHost);
////        return Pair.of(hostId, "not check ,and default success");
//
//
//        Pair<Boolean, String> restPair;
//        try {
//
//            //scp shell to remote host
////            String remoteShellDir = Paths.get(tbHost.getRootDir(), Constant.WEB_SERVER_APP_ID, "shell").toString();
////        SshTools.createDirOnRemote(ip, remoteShellDir, sshUser, sshPort, properties.getSshPrivateKey());
////            shellService.scp(ScpTypeEnum.UP, tbHost.getSshUser(), tbHost.getIp(), tbHost.getSshPort(), Constant.SHELL_CHECK_HOST, remoteShellDir);
//
//            //check
////            String checkHostCommand = String.format("ssh -p %1d %2s@%3s -C \"/bin/bash\" < %4s", tbHost.getSshPort(),tbHost.getSshUser(),tbHost.getIp(), Constant.SHELL_CHECK_HOST);
////            ExecuteResult result = JavaCommandExecutor.executeCommand(checkHostCommand, 0);
////            if (result.failed()) {
////                log.error("javaCommandExecutor exec on localhost command:[{}] result:[{}].", checkHostCommand, result.getExecuteOut() );
////            }
//
//            String checkHostCommand = String.format("sudo bash < %1s", Constant.SHELL_CHECK_HOST);
//            restPair = SshTools.exec(tbHost.getIp(), checkHostCommand, tbHost.getSshUser(), tbHost.getSshPort(), properties.getSshPrivateKey());
//
//
////            return Pair.of(result.success(),result.getExecuteOut());
//        } catch (Exception ex) {
//            log.warn("fail exec method [checkHostEnvironment].", ex);
//            restPair = Pair.of(false, ex.getMessage());
//        }
//
//        //update host status
//        log.info("nodeCheck result:{}", JsonUtils.objToString(restPair));
//        tbHost.setStatus(HostStatusEnum.NORMAL.getId());
//        if (Objects.isNull(restPair) || !restPair.getLeft()) {
//            log.info("fail exec method [checkHostEnvironment].");
//            tbHost.setStatus(HostStatusEnum.CHECK_FAIL.getId());
//        }
//        tbHost.setGmtModified(new Date());
//        hostMapper.updateByPrimaryKey(tbHost);
//
//        Pair<Integer, String> rspPair = Pair.of(hostId, restPair.getRight());
//        log.info("success exec method[checkHostEnvironment] . result:{}", JsonUtils.objToString(rspPair));
//        return rspPair;
//    }


    /**
     * @param example
     * @return
     */
    public BasePageResponse queryHostByPage(TbHostExample example) {
        log.info("start exec method [queryHostByPage]. example:{}", JsonUtils.objToString(example));
        BasePageResponse pageResponse = BasePageResponse.initialize();
        pageResponse.setTotalCount(hostMapper.countByExample(example));
        if (pageResponse.getTotalCount() > 0) {
            example.setOrderByClause(Constant.ORDER_BY_GMT_MODIFIED_DESC);
            List<RspHostVO> rspHostVOList = new ArrayList<>();
            List<TbHost> tbHostList = hostMapper.selectByExample(example);
            for (TbHost tbHost : tbHostList) {
                RspHostVO rspHostVO = rspRspHostVoFromTbHost(tbHost);
                rspHostVOList.add(rspHostVO);
            }
            pageResponse.setData(rspHostVOList);
        }

        log.info("success exec method [queryHostByPage]. result:{}", JsonUtils.objToString(pageResponse));
        return pageResponse;
    }


    /**
     * @param tbHost
     * @return
     */
    private RspHostVO rspRspHostVoFromTbHost(TbHost tbHost) {
        log.debug("start exec method [rspRspHostVoFromTbHost]. tbHost:{}", JsonUtils.objToString(tbHost));
        RspHostVO rspHostVO = new RspHostVO();
        BeanUtils.copyProperties(tbHost, rspHostVO);
        //companyName
        try {
            rspHostVO.setCompanyName(companyMapper.selectNameByPrimaryKey(tbHost.getCompanyId()));
        } catch (Exception ex) {
            log.warn("fail get companyName", ex);
        }

        //org name
        try {
            rspHostVO.setOrgName(orgMapper.selectNameByPrimaryKey(tbHost.getOrgId()));
        } catch (Exception ex) {
            log.warn("fail get orgName", ex);
        }

        log.debug("success exec method [rspRspHostVoFromTbHost]. rspHostVO:{}", JsonUtils.objToString(rspHostVO));
        return rspHostVO;
    }


    /**
     * @param hostId
     * @return
     */
    public TbHost verifyHostId(int hostId) {
        log.info("start exec method [verifyHostId]. hostId:{}", hostId);
        TbHost tbHost = hostMapper.selectByPrimaryKey(hostId);
        if (Objects.isNull(tbHost)) {
            log.warn("fail exec method [verifyHostId]. not found record by hostId:{}", hostId);
            throw new WebServerException(ConstantCode.INVALID_HOST_ID);
        }
        log.info("success exec method [verifyHostId]. result:{}", JsonUtils.objToString(tbHost));
        return tbHost;
    }


    /**
     * @param hostId
     * @return
     */
    public RspHostVO queryHostDetail(Integer hostId) {
        log.info("start exec method [queryHostDetail]. hostId:{}", hostId);
        TbHost tbHost = hostMapper.selectByPrimaryKey(hostId);
        RspHostVO rspHostVO = new RspHostVO();
        BeanUtils.copyProperties(tbHost, rspHostVO);
        log.info("start exec method [queryHostDetail]. result:{}", JsonUtils.objToString(rspHostVO));
        return rspHostVO;
    }


    /**
     * @param hostId
     * @return
     */
    public String getOrgNameByHostId(int hostId) {
        log.debug("start exec method [getOrgNameByHostId]. hostId:{}", hostId);

        TbHost tbHost = hostMapper.selectByPrimaryKey(hostId);
        if (Objects.isNull(tbHost)) {
            log.warn("fail exec method [getOrgNameByHostId]. not found host record by hostId:{}", hostId);
            return null;
        }

        String orgName = orgMapper.selectNameByPrimaryKey(tbHost.getOrgId());
        log.debug("success exec method [getOrgNameByHostId]. hostId:{} result:{}", hostId, orgName);
        return orgName;
    }

    /**
     * @param platform
     * @param creatorAccountId
     * @return
     */
    public long countHostByCreator(PlatformEnum platform, int creatorAccountId) {
        log.debug("start exec method [countHostByCreator]. platform:{} creatorAccountId:{}", platform, creatorAccountId);
        TbHostExample example = MybatisExampleTools.initSampleExample(TbHostExample.class, new TbHost(platform, creatorAccountId));
        long count = hostMapper.countByExample(example);
        log.debug("success exec method [countHostByCreator]. platform:{} creatorAccountId:{} count:{}", platform, creatorAccountId, count);
        return count;
    }
}
